#pragma once
#include "fmod.hpp"
#include "fmod_errors.h"
#include "cocos2d.h"
#include "StringTools.h"
#include <string>
#include <thread>

#define SAFE_RELEASE_FMOD_COMPONENT(__COM__) { if((__COM__)) (__COM__)->release(); (__COM__) = nullptr; }
#define FMOD_ERR_MSGBOX if(result!=FMOD_OK) cocos2d::MessageBox("FMOD ERROR.","ERROR");
#define FMOD_ERR_LOG if(result!=FMOD_OK) CCLOG(string("FMOD ERROR: "+strtool::int2str(result)).c_str());

using namespace FMOD;
using namespace std;
//USING_NS_CC;

class AudioSystem
{
	public:
	AudioSystem();
	~AudioSystem();

	enum SOUNDTYPE
	{
		BGM,
		SFX,
		LOOP_BGM,
		LOAD_BGM
	};

	struct WaveData
	{
		float L = 0;
		float R = 0;
		float MIX = 0;
	};

	struct BGMObject
	{
		Sound* pSnd;
		Channel* pChl;
	}curbgm;

	bool bgmFading;
	private:
	System* pSystem;
	Sound* pCurBGM;
	SoundGroup* pBGMGroup;
	SoundGroup* pSFXGroup;
	Channel* pBGMChannel;
	unsigned int bgmLength;
	int sampleRate;

	vector<Sound*> sfxPool;
	//thread threadBGMSwitch;

	public:
	int loadSoundFromFile(const std::string& pFilename, SOUNDTYPE sndtype, bool isSoftware = true);
	void playLoadedBGM(float volume);
	void playBGM(const std::string & pFilename, float volume);
	BGMObject playBGMReturnCurrentObject(const std::string & pFilename, float volume);
	void playBGMFadeIn(const std::string & pFilename, int fadetime, float volume, int startpos);
	void changeBGMFadeInOut(const std::string & pFilename, int fadetime, float volume, int startpos);
	void pauseBGM();
	void resumeBGM();
	void setBGMPosition(unsigned int posi);
	void setChannelPosition(Channel* channel, unsigned int posi);
	void setBGMVolume(int fadetime, float volume);
	void setChannelVolume(Channel* channel, int fadetime, float volume);
	void setMasterVolume(float volume);
	void stopBGM(bool releaseSound = true);
	void stopAllSound(bool releaseSound = true);
	void releaseBGMsnd();
	void playSFX(int sfxIndex);
	void releaseAllSFX();
	unsigned int getBgmLength();
	unsigned int getBgmPosition();
	WaveData getWaveData();
	int getDSPClockInMS();
	int getSfxPoolSize();

	void update();

	private:

};

